package cheme.Interpreter.AST.Variable;

import cheme.Interpreter.AST.Arithmetic.AstExpression;
import cheme.Interpreter.AST.Arithmetic.AstValue;
import cheme.Interpreter.AST.Interfaces.IAstExpression;
import cheme.Interpreter.AST.Interfaces.IAstIdentifier;
import cheme.Interpreter.AST.Interfaces.IAstVariable;
import cheme.Interpreter.AST.Interfaces.IObserver;
import cheme.Interpreter.AST.Interfaces.ISubject;
import cheme.Interpreter.AST.Interfaces.SubjectCore;

/*
 * Varaible should NOT be expressions!
 */
public class AstVariable 
extends AstExpression 
implements IAstVariable
{
	private IAstIdentifier identifier = null;
	private DeclarationState declarationState = DeclarationState.InferredDeclaration;

	private SubjectCore subjectCore = new SubjectCore(this);
	
	public AstVariable(IAstIdentifier identifier, IAstExpression expression)
	{
		super(expression, null);

		this.identifier = identifier;
		
		if(null != identifier)
		{
			identifier.attach(this);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see edu.wsu.cheme.ChemeVM.AST.Interfaces.IAstVariable#setValue(java.lang.Double)
	 * 
	 * This is a convenience method that wraps up the new value in an AstValue 
	 * and set this variable expression to that value.
	 */
	public void setValue(Double value)
	{
		setExpression(new AstValue(value));
	}

	public void setValueKeepingType(Double value)
	{
		setExpression(new AstExpression(new AstValue(value), getExpression().getType()));
	}
	
	public IAstIdentifier getIdentifier()
	{
		return identifier;
	}
	
	public void setIdentifier(IAstIdentifier identifier)
	{
		this.identifier = identifier;
	}

	public DeclarationState getDeclarationState()
	{
		return declarationState;
	}

	public void setDeclarationState(DeclarationState declarationState)
	{
		this.declarationState = declarationState;
	}

	public void notify(ISubject s)
	{
		notifyObservers();
	}
	
	public void attach(IObserver o)
	{
		subjectCore.attach(o);
	}

	public void detach(IObserver o)
	{
		subjectCore.detach(o);
	}

	public void notifyObservers()
	{
		subjectCore.notifyObservers();
	}
}
